/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package classes;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


public class Converter {

	Data dataOut = new Data();
	Document document;                      //The Document interface represents the entire HTML or XML document. Conceptually, it is the root of the document tree, and provides the primary access to the document's data.
        Polygon poligono1 = new Polygon();      //variabile usata per gestire il poligono
        
        java.awt.Point coordinates = new java.awt.Point(0, 0);
        ArrayList<java.awt.Point> punticlient = new ArrayList<java.awt.Point>();
        
        int n=0;
        
        
	      
	public Data textToObject(String text,int cont1){
		try {
			
                    //parsa la stringa (html del poligono inserito) in ingresso e crea poligoni in java; sfutta metodo CreateObjects specificato dopo
                    createObjects( text, cont1);  
			
		} catch (SAXException e) {
			// TODO Auto-generated catch block
		} catch (IOException e) {    //rileva eccezioni per errori I/O
			// TODO Auto-generated catch block
		} catch (ParserConfigurationException e) {  //Indicates a serious configuration error
			// TODO Auto-generated catch block
		}
		
                //inseriamo il poligono creato in java nell'oggetto dataOut (array di shape) e lo ritorniamo
                dataOut.getShapes().add(poligono1);
                return dataOut;               
		
	}
	
	public String dataToSvg(Data dataIn){
                     

	        //Creea un'istanza di SVG Generator.
	        SVGGraphics2D svgGenerator = new SVGGraphics2D(document);  //VGGraphics2D is a new implementation of that interface(Graphics2D) that generates SVG content instead of drawing to a screen or a printer.
                
                
                
                //analizza dataIn e disegna punti o shape, a seconda di quello che trova nell'aray
                for(java.awt.Shape s : dataIn.getShapes()){
	        	this.paintShape(svgGenerator,s);
	        }
	        for(java.awt.Point s : dataIn.getPoints()){
	        	this.paintPoint(svgGenerator,s);
	        }
	       
	        boolean useCSS = false; // we want to use CSS style attributes?
	        
	        StringWriter f = new StringWriter();
	        try {
				svgGenerator.stream(f, useCSS);
				
			} catch (SVGGraphics2DIOException e) {
				
			}
	        
			String buffer = f.toString();
	        
	        String buffer1 = buffer.replace("<?xml version=\"1.0\"?>" ,"");
	        
	        
	        return buffer1;
	        
	    }
		
		private void paintShape(Graphics2D g2d,java.awt.Shape shape) { //svg per disegnare il risultato come forma
			Color c;
                        g2d.setStroke(new BasicStroke(2));
                        float alpha = (float) 0.75f;
                        c=new Color(230,37,20,0); //colore dell'area 
			g2d.setPaint(c);  //assegna il colore
                        
 			g2d.draw(shape); //disegna la sagoma del poligono
                        g2d.fill(shape);  //riempe il poligono
	 
	    }
		private void paintPoint(Graphics2D g2d,Point point) { //svg per disegnare il risultato come punto
			
			g2d.setPaint(Color.BLACK); //assegna colore
                        g2d.setStroke(new BasicStroke(4)); //scegli tratto
                        g2d.drawOval(point.x-8, point.y-8, 16, 16); //disegna un cerchio intorno al punto selezionato
                       
 
	    }
	
	
	
	
	private void createObjects( String text, int cont1) throws SAXException, IOException, ParserConfigurationException{

		
            //Contains an internal buffer that stores the bytes read from the input stream
            //.getBytes() codifica la stringa in una sequenza di byte, ritorna un array di bytes byte[]
            ByteArrayInputStream str = new ByteArrayInputStream(text.getBytes());
  
	     
            
            //faccio il parse e ottengo un oggetto document navigabile!!
            document =  DocumentBuilderFactory   //Class DocumentBuilder: Defines a factory API that enables applications to obtain a parser that produces DOM object trees from XML documents
	    .newInstance()                           //nuova istanza di DocumentBuilderFactory che fornisce API per il parsing di documenti xml
	    .newDocumentBuilder()
	    .parse(str);     
             
      
	    //getDocumentElement() restituisce il nodo root che per un documento html è l'elemento con il TAG "html"
	    Element rootElement = document.getDocumentElement();  //This is a convenience attribute that allows direct access to the child node that is the root element of the document. For HTML documents, this is the element with the tagName "HTML".
            
            
	    //metodo per navigare il documento 
	    walkNode(rootElement, cont1);  //The Element interface represents an element in an HTML or XML document.    
	
	}
	
        
        
	private  void walkNode(Node theNode,int cont1) {
		
                
             
            NodeList children = theNode.getChildNodes(); //A NodeList that contains all children of this node.
                                                         //The items in the NodeList are accessible via an integral index, starting from 0
        
             
            
            //ciclo sui figli del nodo selezionato
            for (int i = 0; i < children.getLength(); i++) {
			Node aNode = children.item(i);   //item(i) serve per prendere il nodo i-esimo  
                        
                        
                        //se il nodo ha figli faccio una chiamata ricorsiva
                        if (aNode.hasChildNodes())
				walkNode(aNode, cont1);
			
                        
                        //altrimenti mi trovo su una foglia 
                        else{
//				
				Node nodeWidth = aNode.getAttributes().getNamedItem("width");
				Node nodeHeight = aNode.getAttributes().getNamedItem("height");
                                
                                //.getAttributes() ritorna un NamedNodeMap che serve per rappresentare i nodi accessibili con un nome
                                //.getNamedItem("width") è un metodo di NamedNodeMap che trova un nodo dal suo nome
				//check if is a point
				if( nodeHeight!=null && nodeWidth!=null ){
                                    
                                        //controlliamo se il nodo è una rect
					if( aNode.getNodeName().equals("rect")  //getNodeName:restituisce una stringa ovvero il nome del nodo
                                                
                                               
                                                        //controlliamo anche se è una rect di 1px o 1 cioè un punto sia in lunghezza che in larghezza
							&& (nodeWidth.getNodeValue().equals("1px")|| nodeWidth.getNodeValue().equals("1"))   //The value of this node, depending on its type; see the table above
							&& (nodeHeight.getNodeValue().equals("1px")||nodeHeight.getNodeValue().equals("1")) ){
                                            
                                            
						//in caso positivo prendiamo le coordinate x e y del punto 
						int x = Integer.parseInt(aNode.getAttributes().getNamedItem("x").getNodeValue().replace("px", "")); //replace: Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar
						int y = Integer.parseInt(aNode.getAttributes().getNamedItem("y").getNodeValue().replace("px", ""));
						
                                                coordinates.setLocation(x,y);
                                                
                                                //-------nota: Integer.parseInt----------------
                                                //parseInt(string s): Parses the string argument as a signed decimal integer.
                                                //Ogni classe wrapper definisce metodi per estrarre il valore della variabile incapsulata al suo interno e viceversa
                                                //Integer.parseInt fa la conversione da stringa ad intero, è un metodo statico, non richiede un istanza!!
                                                //---------------------------------------------
                                                
                                                
//                                               Point point = new Point(x, y);
                                                
                                                //prendiamo i primi n punti e li mettiamo nel primo poligono
                                                if (n < cont1) {
                                                   poligono1.addPoint(x, y);
                                                   
                                                   //F
                                                   punticlient.add(coordinates.getLocation());
                                                   n++;
                                                } 
                                               						
                                                //abbiamo creato i poligoni in java contenenti gli stessi poligoni disegnati sul client
                                                
                                                //dataOut è un oggetto di tipo Data che possiede come attributi un array di punti
                                                //chiamato points ed un array di shapes, la classe shape è un'interfaccia che in java serve per rappresentare figure
                                                //viene implementata da classi quali Line2D, Point2D etc..
                                                //getPoints è un metodo di Data che serve per estrarre il vettore di punti!!
                                                
					}else if(aNode.getNodeName().equals("rect")){

					}
				}
				
			}

		}
	}



	public Data getDataOut() {
		return dataOut;
	}
} 
